package com.example.websocket.excel.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.sql.Clob;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class StringUtils {
	/**
	 * 扩展并右对齐字符串，用指定字符串填充左边。
	 * 
	 * <pre>
	 * StringUtil.alignRight(null, *, *)      = null
	 * StringUtil.alignRight("", 3, "z")      = "zzz"
	 * StringUtil.alignRight("bat", 3, "yz")  = "bat"
	 * StringUtil.alignRight("bat", 5, "yz")  = "yzbat"
	 * StringUtil.alignRight("bat", 8, "yz")  = "yzyzybat"
	 * StringUtil.alignRight("bat", 1, "yz")  = "bat"
	 * StringUtil.alignRight("bat", -1, "yz") = "bat"
	 * StringUtil.alignRight("bat", 5, null)  = "  bat"
	 * StringUtil.alignRight("bat", 5, "")    = "  bat"
	 * </pre>
	 * @param str 要对齐的字符串
	 * @param size 扩展字符串到指定宽度
	 * @param padStr 填充字符串
	 * @return 扩展后的字符串，如果字符串为<code>null</code>，则返回<code>null</code>
	 */
	public static String alignRight(String str, int size, String padStr) {
		if (str == null) {
			return null;
		}
		if ((padStr == null) || (padStr.length() == 0)) {
			padStr = " ";
		}
		int padLen = padStr.length();
		int strLen = str.length();
		int pads = size - strLen;

		if (pads <= 0) {
			return str;
		}

		if (pads == padLen) {
			return padStr.concat(str);
		} else if (pads < padLen) {
			return padStr.substring(0, pads).concat(str);
		} else {
			char[] padding = new char[pads];
			char[] padChars = padStr.toCharArray();

			for (int i = 0; i < pads; i++) {
				padding[i] = padChars[i % padLen];
			}

			return new String(padding).concat(str);
		}
	}
	/**
	 * 根据表达式计算结果，支持+、-、*、/和括弧嵌套
	 * @param ex
	 * @param datas
	 * @return
	 */
	public static double expression(String ex, Map<String, Double> counters){
		String reg = "\\(\\s*([^\\(\\)]+)\\s*\\)";
		StringBuffer express = new StringBuffer(ex);
		Pattern p = Pattern.compile(reg);
		Matcher m = p.matcher(ex);
		while(m.find()){//如果表达式有括弧，先计算括弧里的表达式
			StringBuffer sb = new StringBuffer();
			Matcher find = p.matcher(express);
			while(find.find()){//找到一个括弧计算一个
				String expression = find.group(1);
				double count = _expression(expression, counters);
				String rp = toString(count, 2);
				if(count < 0)
					rp = "[" + rp +"]";//标注负数
				find.appendReplacement(sb, rp);
			} 
			find.appendTail(sb);
			express = sb;
			m.reset(sb);
		}
		return _expression(express.toString(), counters);
	}
	/**
     * 计算表达式的值，只支持“+ - * / ”运算
     * @param expression
     * @param param
     * @return
     */
	private static double _expression(String expression, Map<String, Double> counters) {
		Pattern p = Pattern.compile("\\s*\\[?(-?[^\\+\\-\\*\\/\\[\\]]+)\\]?\\s*([\\+\\-\\*\\/])?");
		Matcher m = p.matcher(expression);
		List<String> ex = new ArrayList<String>();//运算符
		List<String> keys = new ArrayList<String>();//值或者key
		while (m.find()) {
			String key = m.group(1).trim();
			keys.add(key);
			if (m.group(2) != null){
				ex.add(m.group(2));
			}
		}
		if (ex.size() > 0) {// 有运算符，是数值运算
			List<Double> w = new ArrayList<Double>();
			for (String key : keys) {
				w.add(_expressionGetValue(key, counters));
			}
			for (int index = 0; index < ex.size(); index++) {// 先计算乘和除
				String c = ex.get(index);
				if (c.equals("*")) {
					Double f = w.remove(index);
					Double t = w.remove(index);
					Double r = null;
					if (f != null && t != null) {
						r = ((double) f) * ((double) t);
					}
					w.add(index, r);
					ex.remove(index);
					index--;
					continue;
				} else if (c.equals("/")) {
					Double f = w.remove(index);
					Double t = w.remove(index);
					Double r = null;
					if (f != null && t != null && t != 0) {
						r = ((double) f) / ((double) t);
					}
					w.add(index, r);
					ex.remove(index);
					index--;
					continue;
				}
			}
			for (int index = 0; index < ex.size(); index++) {
				String c = ex.get(index);
				if (c.equals("+")) {
					Double f = w.remove(index);
					Double t = w.remove(index);
					Double r = null;
					if (f != null && t != null) {
						r = ((double) f) + ((double) t);
					}
					w.add(index, r);
					ex.remove(index);
					index--;
					continue;
				} else if (c.equals("-")) {
					Double f = w.remove(index);
					Double t = w.remove(index);
					Double r = null;
					if (f != null && t != null) {
						r = ((double) f) - ((double) t);
					}
					w.add(index, r);
					ex.remove(index);
					index--;
					continue;
				}
			}
			Double cent = w.get(0);// 运算结果
			return cent == null ? 0d : (cent.doubleValue() == 0 ? 0d : cent.doubleValue());
		} else {
			return _expressionGetValue(keys.get(0), counters);
		}
	}
	/**
	 * 取得参数值
	 * @param key
	 * @param counters
	 * @return
	 */
	private static Double _expressionGetValue(String key, Map<String, Double> counters){
		int direct = 1;
		if(key.startsWith("-")){//负值
			key = key.substring(1);
			direct = -1;
		}
		Double v = counters.get(key);
		if(v == null){
			if(isDouble(key)){//判断是否是数字，是数字直接加入结果计算
				v = Double.parseDouble(key);
			}else{//不是数字，则赋0
				v = 0d;
			}
		}
		return (v * direct);
	}
	/**
	 * 字符串首字母大写
	 * @param string
	 * @return
	 */
	public static String firstUpperCase(String string){
		return new StringBuffer(string.substring(0, 1).toUpperCase()).append(string.substring(1)).toString();
	}
	
	/**
	 * 字符串首字母小写
	 * @param string
	 * @return
	 */
	public static String firstLowerCase(String string){
		return new StringBuffer(string.substring(0, 1).toLowerCase()).append(string.substring(1)).toString();
	}
	/**
	 * 将类似2003-12-02 23:12:39格式的字符串转换成为日期
	 * @param ds
	 * @return
	 */
	public static Date toDate(String ds){
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date d=null;
		try {
			d = sdf.parse(ds.trim());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return d;
	}
	/**
	 * 将对象转换成String 
	 * 	数值直接转字符串，去除科学记数法相关信息
	 * 	日期：转“yyyy-MM-dd”格式，忽略时间
	 * 	数组：toString()方法返回值
	 * 	其它基本类型：String.valueOf()；
	 * 	其他：toString()
	 * @param value 转换的对象
	 * @return 字符串值
	 */
	public static String toString(Object value){
		if(value == null)
			return null;
		if(value instanceof String)
			return (String)value;
		String result = null;
		Class<?> c = value.getClass();
		NumberFormat numberFormat = new DecimalFormat("#");
		numberFormat.setMaximumFractionDigits(340);
		if(c.isArray()){//数组
			Object[] vs = ArrayUtils.toArray(value);
			for (int i = 0; i < vs.length; i++) {
				vs[i] = toString(vs[i]);
			}
			result = toString(vs);
		} else if(c.isPrimitive()){//基本类型
			if(c.equals(double.class) 
					|| c.equals(float.class)){
				result = numberFormat.format(value);
			}else{
				result = String.valueOf(value);
			}
		} else if(value instanceof Number){//数值对象
			result = numberFormat.format(value);
		} else if(value instanceof Date){//日期对象
			DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
			result = dateFormat.format((Date)value);
		} else{//其它对象
			result = value.toString().trim();
		}
		return result;
	}
	/**
	 * 将数组转换成“a1,a2,a2”形式的字符串
	 * @param array
	 * @return
	 */
	public static String toString(Object[] array){
		return toString(array, ",");
	}
	/**
	 * 将数组转换成“a1,a2,a2”形式的字符串
	 * @param array
	 * @return
	 */
	public static String toString(Object[] array, String div){
		return array == null ? "" :
			Arrays.stream(array).map(StringUtils::toString)
				.collect(Collectors.joining(div == null ? "" : div));
	}
	/**
	 * 将Collection存放的数据转换成“XX,XX”形式的字符串
	 * @param collection
	 * @return
	 */
	public static <T, C extends Collection<T>> String toString(C collection){
		return toString(collection, ",");
	}
	/**
	 * 将Collection存放的数据转换成“XX,XX”形式的字符串，以div做分隔符，空值null以""取代
	 * @param collection 转换的集合
	 * @return 格式化字符串
	 */
	public static <T, C extends Collection<T>> String toString(C collection, String div){
		return collection == null || collection.size() <= 0 ? "" : 
			collection.stream().map(StringUtils::toString)
				.collect(Collectors.joining(div == null ? "" : div));
	}
	/**
	 * 将Clob数据转换成String
	 * @param clob 转换数据对象
	 * @return String 字串
	 */
	public static String toString(Clob clob){
		try {
			StringBuffer sb = new StringBuffer();
			char[] c = new char[60000];
			Reader r = new BufferedReader(clob.getCharacterStream());
			int l;
			while((l = r.read(c)) != -1){
				sb.append(c, 0, l);
			}
			return sb.toString();
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}
	/**
	 * 将double转化字符串，去除科学计数法
	 * @param d
	 * @return
	 */
	public static String toString(Double d){
		if(d == null)
			return null;
		return toString(d, 0);
	}
	/**
	 * 将double转化字符串，去除科学计数法
	 * @param d
	 * @param digits
	 * @return
	 */
	public static String toString(Double d, int digits){
		if(d == null)
			return null;
		DecimalFormat df = new DecimalFormat();
		df.setMaximumFractionDigits(99);
		df.setMinimumFractionDigits(digits);
		df.setGroupingUsed(false);
		return df.format(d);
	}
	/**
	 * 将字符转换成数组，并存储到容器中，去除首尾空格
	 * @param str 字符串
	 * @param split 分隔符
	 * @return
	 */
	public static List<String> toArray(String str, String regex){
		List<String> strlist = new ArrayList<String>();
		if(str != null && regex != null){
			String[] strArray = str.split(regex);
			for (int i = 0; i < strArray.length; i++) {
				strlist.add(strArray[i].trim());
			}
		}
		return strlist;
	}
	/**
	 * 将字符转换成数组，并存储到容器中，去除首尾空格，以“,”作为分隔符
	 * @param str 字符串
	 * @return
	 */
	public static List<String> toArray(String str){
		return toArray(str, ",");
	}
	/**
	 * 将“a1,a2,a2”转换成“'a1','a2','a3'”形式的字符串，用于SQL中的in字段
	 * @param array
	 * @return
	 */
	public static String toArrayString(String arrayString){
		if(arrayString != null){
			String regex = "^\\s*'?([^']*)'?\\s*$";
			return Arrays.stream(arrayString.split(",")).map(s -> s.replaceAll(regex, "'$1'")).collect(Collectors.joining(", "));
		}
		return null;
	}
	
	/**
	 * 将数字格式的金额转换为中文大写显示，非法字符返回空字符串
	 * @param data
	 * @return
	 */
	public static String toCurrencyCHA(String data){
		if(data == null)
			return null;
		if (!Pattern.matches("^-?(0|[1-9]\\d*)(\\.\\d+)?$", data))//数据非法
			return null;
		String unit = "京亿万仟佰拾兆万仟佰拾亿仟佰拾万仟佰拾元角分", d = "";
		//正负符号
		if(data.startsWith("-")){
			d = "负";
			data = data.substring(1);
		}
		//格式化为保留小数点两位
		data += "00";
		int p = data.indexOf('.');
		if (p >= 0)
			data = data.substring(0, p) + data.substring(p + 1, p + 3);
		
		StringBuffer str = new StringBuffer(d);
		unit = unit.substring(unit.length() - data.length());
		for (int i = 0; i < data.length(); i++){
			str.append("零壹贰叁肆伍陆柒捌玖".charAt(Character.getNumericValue(data.charAt(i))));
			str.append(unit.charAt(i));
		}
		return str.toString().replaceAll("零(仟|佰|拾|角)", "零").replaceAll("(零)+", "零").replaceAll(
				"零(兆|万|亿|元)", "$1").replaceAll("(兆|亿)万", "$1").replaceAll("(京|兆)亿",
				"$1").replaceAll("(京)兆", "$1").replaceAll("(京|兆|亿|仟|佰|拾)(万?)(.)仟",
				"$1$2零$3仟").replaceAll("^元零?|零分", "").replaceAll("(元|角)$", "$1整");
	}
	/**
	 * 去除字符串前后空格
	 * @param str
	 * @return
	 */
	public static String trim(String str){
		if(str==null)
			return str;
		else
			return str.trim();
	}
	/**
	 * 验证邮箱
	 * @param name 验证字窜
	 * @return 是：true，否：false
	 */
	public static boolean isEmail(String name){
		return Pattern.matches("^[\\w-.]+@([\\w-]+\\.)+[\\w]{2,3}$", name);
	}
	/**
	 * 验证是否是手机号码
	 * @param name 验证字窜
	 * @return 是：true，否：false
	 */
	public static boolean isMobile(String name){
		return Pattern.matches("^1[358]\\d{9}$", name);
	}
	/**
	 * 验证是否是数字
	 * @param name 验证字窜
	 * @return 是：true，否：false
	 */
	public static boolean isInteger(String name){
		return Pattern.matches("^\\d+$", name);
	}
	/**
	 * 验证是否是数字
	 * @param name 验证字窜
	 * @return 是：true，否：false
	 */
	public static boolean isDouble(String name){
		return Pattern.matches("^\\d+\\.?\\d*$", name);
	}
	/**
	 * 验证是否是保留至少digits位小数点的浮点数字
	 * @param name 验证字窜
	 * @return 是：true，否：false
	 */
	public static boolean isDouble(String name, int digits){
		StringBuffer rex = new StringBuffer("^\\d+");
		if(digits <= 0){
			rex.append("$");
		}else{
			rex.append("\\.\\d{");rex.append(digits);rex.append(",}$");
		}
		return Pattern.matches(rex.toString(), name);
	}
	/**
	 * 格式化字符串，{0}替换成正式数据
	 * @param input 需格式化的字符串
	 * @param reg 替换字串
	 * @return 格式化结果
	 */
	public static String format(String input, String... reg){
		for (int i = 0; i < reg.length; i++) {
			if(reg[i] == null)
				reg[i] = "";
			input = input.replaceAll("\\{"+i+"\\}", reg[i]);
		}
		return input;
	}
	/**
	 * 验证字串ffix是否在字串filter中，其中filter字串以“,”分隔多个子字串
	 * @param filter 验证的是否包含的字串
	 * @param ffix 验证的字串
	 * @return 验证结果
	 */
	public static boolean isFileFix(String filter, String ffix){
		String[] fixes = filter.split(",");
		List<String> flist = new ArrayList<String>();
		for(String fix : fixes){
			if(fix != null)
				flist.add(fix.trim());
		}
		return flist.contains(ffix);
	}
	/**
	 * 在正则表达式字串的保留字符前增加转义符
	 * @param regex 正则表达式
	 * @return 转换后的字串
	 */
	public static String format(String regex){
		regex = regex.replaceAll("\\\\", "\\\\\\\\");//\.^${}()[]|
		regex = regex.replaceAll("\\.", "\\\\.");
		regex = regex.replaceAll("\\^", "\\\\^");
		regex = regex.replaceAll("\\$", "\\\\$");
		regex = regex.replaceAll("\\{", "\\\\{");
		regex = regex.replaceAll("\\}", "\\\\}");
		regex = regex.replaceAll("\\(", "\\\\(");
		regex = regex.replaceAll("\\)", "\\\\)");
		regex = regex.replaceAll("\\[", "\\\\[");
		regex = regex.replaceAll("\\]", "\\\\]");
		return regex;
	}
	
}
